package com.example.android.plugin.framework;

import java.lang.reflect.Field;

import com.example.android.plugin.framework.beans.Plugin;
import com.example.android.plugin.framework.util.Utils;

import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;

public class PluginDescription<T> {
	private Class<T> clazz;

	public PluginDescription(Class<T> clazz) {
		this.clazz = clazz;
	}

	public T getDescription(Context context, Plugin plugin)
			throws ClassNotFoundException, IllegalAccessException,
			InstantiationException, NameNotFoundException,
			IllegalArgumentException, SecurityException, NoSuchFieldException {

		Context targetContext = context.createPackageContext(
				plugin.getPkgInfo().packageName, Context.CONTEXT_INCLUDE_CODE
						| Context.CONTEXT_IGNORE_SECURITY);

		ClassLoader loader = Utils.changeClassLoaderParent(targetContext,
				context.getClassLoader());
		Class<?> c = loader.loadClass(plugin.getDescription());
		Object des = c.newInstance();

		T sor = clazz.newInstance();

		Field[] fields = clazz.getSuperclass().getDeclaredFields();
		for (Field f : fields) {
			f.setAccessible(true);
			Field tf = getClassField(c.getSuperclass(), f.getName());
			tf.setAccessible(true);
			f.set(sor, tf.get(des));
		}

		return sor;
	}

	private Field getClassField(Class<?> clazz, String fieldName) {
		Field[] declaredFields = clazz.getDeclaredFields();
		for (Field field : declaredFields) {
			// 注意：这里判断的方式，是用字符串的比较。很傻瓜，但能跑。要直接返回Field。我试验中，尝试返回Class，然后用getDeclaredField(String
			// fieldName)，但是，失败了
			if (field.getName().equals(fieldName)) {
				return field;// define in this class
			}
		}

		Class<?> superclass = clazz.getSuperclass();
		if (superclass != null) {// 简单的递归一下
			return getClassField(superclass, fieldName);
		}
		return null;
	}
}